//
//  Extension.swift
//  TJShopSDK
//
//  Created by 庞成龙 on 2022/4/6.
//

import Foundation
import UIKit

let kDefaultMultiple:CGFloat = 1.4

struct YDRectCorner {
    var topLeft: CGFloat
    var topRight: CGFloat
    var bottomLeft: CGFloat
    var bottomRight: CGFloat
    // 创建四个角不同半径大小的圆角结构体
    init(topLeft: CGFloat = 0, topRight: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0) {
        self.topLeft = topLeft
        self.topRight = topRight
        self.bottomLeft = bottomLeft
        self.bottomRight = bottomRight
    }
    // 创建四个角相同半径大小的圆角结构体
    init(all cornerRadius: CGFloat) {
        self.topLeft = cornerRadius
        self.topRight = cornerRadius
        self.bottomLeft = cornerRadius
        self.bottomRight = cornerRadius
    }
}


/// 视图切角
internal extension UIView {
    /// 视图切圆角
    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        let maskPath = UIBezierPath(
            roundedRect: bounds,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius))
        
        let shape = CAShapeLayer()
        shape.path = maskPath.cgPath
        layer.mask = shape
    }
    
    /// 视图切圆角，四个角可不同
    func addCorner(_ corners: YDRectCorner, frame: CGRect? = nil) {
        let rect: CGRect = frame ?? self.bounds
        // 绘制路径
        let path = CGMutablePath()
        let topLeftRadius = corners.topLeft
        let topLeftCenter = CGPoint(x: rect.minX + topLeftRadius, y: rect.minY + topLeftRadius)
        path.addArc(center: topLeftCenter, radius: topLeftRadius, startAngle: Double.pi, endAngle: Double.pi * 1.5, clockwise: false)
        let topRightRadius = corners.topRight
        let topRightCenter = CGPoint(x: rect.maxX - topRightRadius, y: rect.minY + topRightRadius)
        path.addArc(center: topRightCenter, radius: topRightRadius, startAngle: Double.pi * 1.5, endAngle: Double.pi * 2, clockwise: false)
        let bottomRightRadius = max(corners.bottomRight, 0)
        let bottomRightCenter = CGPoint(x: rect.maxX - bottomRightRadius, y: rect.maxY - bottomRightRadius)
        path.addArc(center: bottomRightCenter, radius: bottomRightRadius, startAngle: 0, endAngle: Double.pi * 0.5, clockwise: false)
        let bottomLeftRadius = max(corners.bottomLeft, 0)
        let bottomLeftCenter = CGPoint(x: rect.minX + bottomLeftRadius, y: rect.maxY - bottomLeftRadius)
        path.addArc(center: bottomLeftCenter, radius: bottomLeftRadius, startAngle: Double.pi * 0.5, endAngle: Double.pi, clockwise: false)
        path.closeSubpath()
        // 给layer添加遮罩
        let layer = CAShapeLayer()
        layer.path = path
        self.layer.mask = layer
    }
    
    // 设置横向渐变色
    func addCrosswiseGradientLayer(colors : [UIColor]) {
        let gradientLayer: CAGradientLayer = CAGradientLayer()
        gradientLayer.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.locations = [0, 1]
                
        let startPoint: CGPoint = CGPoint(x: 0, y: 0.5)
        let endPoint: CGPoint = CGPoint(x: 1, y: 0.5)
                
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
                
        self.layer.addSublayer(gradientLayer)
    }
    
    // 设置竖向渐变色
    func addVerticalGradientLayer(colors : [UIColor]) {
        let gradientLayer: CAGradientLayer = CAGradientLayer()
        gradientLayer.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.locations = [0, 1]
                
        let startPoint: CGPoint = CGPoint(x: 0.5, y: 0)
        let endPoint: CGPoint = CGPoint(x: 0.5, y: 1)
                
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
                
        self.layer.addSublayer(gradientLayer)
    }

    // 生成传入的frame大小的图片
    func snapshot(frame: CGRect) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(frame.size, false, UIScreen.main.scale)
        if let context = UIGraphicsGetCurrentContext() {
//            drawHierarchy(in: frame, afterScreenUpdates: true)
//            let screenShot = UIGraphicsGetImageFromCurrentImageContext()
//            UIGraphicsEndImageContext()
//            return screenShot
            self.layer.render(in: context)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }
        return nil
    }
}


/// 取消高亮状态
extension UIButton {
    open override var isHighlighted: Bool {
        set{}
        get {
            return false
        }
    }
}
/// 按钮防多次点击
typealias ActionBlock = ((UIButton)->Void)

internal extension UIButton {
    
    private struct AssociatedKeys {
        static var ActionBlock = "ActionBlock"
        static var ActionDelay = "ActionDelay"
    }
    
    /// 运行时关联
    private var actionBlock: ActionBlock? {
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.ActionBlock, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.ActionBlock) as? ActionBlock
        }
    }
    
    private var actionDelay: TimeInterval {
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.ActionDelay, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.ActionDelay) as? TimeInterval ?? 0
        }
    }
    
    /// 点击回调
    @objc private func btnDelayClick(_ button: UIButton) {
        actionBlock?(button)
        isUserInteractionEnabled = false
        DispatchQueue.main.asyncAfter(deadline: .now() + actionDelay) { [weak self] in
            print("恢复时间\(Date())")
            self?.isUserInteractionEnabled = true
        }
    }
    
    /// 添加点击事件
    func addAction(_ delay: TimeInterval = 0, action: @escaping ActionBlock) {
        addTarget(self, action: #selector(btnDelayClick(_:)) , for: .touchUpInside)
        actionDelay = delay
        actionBlock = action
    }
}
/// button 改变图片和文字的位置
internal extension UIButton {
    enum ButtonImagePosition {
        case top          //图片在上，文字在下，垂直居中对齐
        case bottom       //图片在下，文字在上，垂直居中对齐
        case left         //图片在左，文字在右，水平居中对齐
        case right        //图片在右，文字在左，水平居中对齐
    }
    /// - Description 设置Button图片的位置
    /// - Parameters:
    ///   - style: 图片位置
    ///   - spacing: 按钮图片与文字之间的间隔
    func imagePosition(style: ButtonImagePosition, spacing: CGFloat) {
        //得到imageView和titleLabel的宽高
        let imageWidth = self.imageView?.frame.size.width
        let imageHeight = self.imageView?.frame.size.height
        var labelWidth: CGFloat! = 0.0
        var labelHeight: CGFloat! = 0.0
        labelWidth = self.titleLabel?.intrinsicContentSize.width
        labelHeight = self.titleLabel?.intrinsicContentSize.height
        //初始化imageEdgeInsets和labelEdgeInsets
        var imageEdgeInsets = UIEdgeInsets.zero
        var labelEdgeInsets = UIEdgeInsets.zero
        //根据style和space得到imageEdgeInsets和labelEdgeInsets的值
        switch style {
        case .top:
            //上 左 下 右
            imageEdgeInsets = UIEdgeInsets(top: -labelHeight-spacing/2, left: 0, bottom: 0, right: -labelWidth)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWidth!, bottom: -imageHeight!-spacing/2, right: 0)
            break;
        case .left:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: -spacing/2, bottom: 0, right: spacing)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: spacing/2, bottom: 0, right: -spacing/2)
            break;
        case .bottom:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -labelHeight!-spacing/2, right: -labelWidth)
            labelEdgeInsets = UIEdgeInsets(top: -imageHeight!-spacing/2, left: -imageWidth!, bottom: 0, right: 0)
            break;
        case .right:
            imageEdgeInsets = UIEdgeInsets(top: 0, left: labelWidth+spacing/2, bottom: 0, right: -labelWidth-spacing/2)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWidth!-spacing/2, bottom: 0, right: imageWidth!+spacing/2)
            break;
        }
        self.titleEdgeInsets = labelEdgeInsets
        self.imageEdgeInsets = imageEdgeInsets
    }
}

extension UITextField {
    /// 需先设置placeHolder后再设置颜色方可生效
    var placeHolderColor: UIColor {
        set{
            guard let holder = self.placeholder, !holder.isEmpty else { return }
            self.attributedPlaceholder = NSAttributedString(string: holder, attributes: [.foregroundColor: newValue])
        }
        get{return .black}
    }
}

/// 快速创建label
internal extension UILabel {
    class func createLab(text:String, textColor:UIColor, font:UIFont) -> UILabel {
        let lab = UILabel()
        lab.text = text
        lab.textColor = textColor
        lab.font = font
        lab.textAlignment = .left
        return lab
    }
    
    // 创建富文本。“使用10康豆”，对数字特殊处理
//    class func createRichText(text: String, color: UIColor, font: UIFont) -> ASAttributedString {
//        var string: ASAttributedString = ASAttributedString.init(string: text, .background(.clear))
//        string.add(attributes: [.foreground(color), .font(font)], checkings: [.regex("[0-9]|%")])
//        return string
//    }

}

extension UIImage {
    
//    + (CIImage *)creatQRcodeWithUrlstring:(NSString *)urlString{
//
//        // 1.实例化二维码滤镜
//        CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//        // 2.恢复滤镜的默认属性 (因为滤镜有可能保存上一次的属性)
//        [filter setDefaults];
//        // 3.将字符串转换成NSdata
//        NSData *data  = [urlString dataUsingEncoding:NSUTF8StringEncoding];
//        // 4.通过KVO设置滤镜, 传入data, 将来滤镜就知道要通过传入的数据生成二维码
//        [filter setValue:data forKey:@"inputMessage"];
//        // 5.生成二维码
//        CIImage *outputImage = [filter outputImage];
//        return outputImage;
//    }
    
    ///--生成二维码
    static func creatQRcodeWithUrlstring(urlString: String) -> CIImage {
        // 1.实例化二维码滤镜
        let filter = CIFilter.init(name: "CIQRCodeGenerator")
        // 2.恢复滤镜的默认属性 (因为滤镜有可能保存上一次的属性)
        filter?.setDefaults()
        // 3.将字符串转换成NSdata
        let data = urlString.data(using: .utf8)
        // 4.通过KVO设置滤镜, 传入data, 将来滤镜就知道要通过传入的数据生成二维码
        filter?.setValue(data, forKeyPath: "inputMessage")
        // 5.生成二维码
        let outputImage = filter?.outputImage
        return outputImage!
    }
    
    // 高清处理 -- 生成二维码
    static func createUIImageFromCIImage(urlString: String, size: CGFloat) -> UIImage {
        
        let image = self.creatQRcodeWithUrlstring(urlString: urlString)
        
        let extent = image.extent.integral
        let scale = min(size / extent.width, size / extent.height)
        
        /// Create bitmap
        let width: size_t = size_t(extent.width * scale)
        let height: size_t = size_t(extent.height * scale)
        let cs: CGColorSpace = CGColorSpaceCreateDeviceGray()
        let bitmap: CGContext = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 0, space: cs, bitmapInfo: 1)!
        
        ///
        let context = CIContext.init()
        let bitmapImage = context.createCGImage(image, from: extent)
        bitmap.interpolationQuality = .none
        bitmap.scaleBy(x: scale, y: scale)
        bitmap.draw(bitmapImage!, in: extent)
        
        let scaledImage = bitmap.makeImage()
        return UIImage.init(cgImage: scaledImage!)
    }
    
}


import CommonCrypto
/// 富文本赋值
internal extension String {
    
    /// 判断是否为空
    var empty: Bool {
        let trimmedStr = self.trimmingCharacters(in: .whitespacesAndNewlines)
        return trimmedStr.isEmpty
    }
    /// 判断字符串不为空
    var notEmpty: Bool {
        return !empty
    }
    
    /// 获取字符串MD5值
    var md5: String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)
        
        let hash = NSMutableString()
        
        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }
        
        result.deallocate()
        return hash as String
    }
    
    
    /// converting a string to an attributedString
    /// - Parameters:
    ///   - color: the value for .foregroundColor key
    ///   - font: the value for .font key
    ///   - lineHeight: the height of every text line
    ///   - alignment: the text alignment of the paragraph
    ///   - wordSpaceing: the text chat spacing
    /// - Returns: an attributedString
    func attributed(color: UIColor,
                    font: UIFont,
                    lineHeight: CGFloat? = nil,
                    baselineOffset: CGFloat? = nil,
                    lineBreakMode: NSLineBreakMode = .byTruncatingTail,
                    saleColor: UIColor? = nil,
                    alignment: NSTextAlignment = .left,
                    wordSpaceing: CGFloat? = nil)
    -> NSAttributedString {
        var attributes: [NSAttributedString.Key : Any] = [.foregroundColor: color, .font: font]
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = lineBreakMode
        paragraphStyle.alignment = alignment
        
        if let lineHeight = lineHeight {
            paragraphStyle.minimumLineHeight = lineHeight
            paragraphStyle.maximumLineHeight = lineHeight
            attributes[.baselineOffset] = (lineHeight - font.lineHeight) / 4.0
        }
        
        if let baselineOffset = baselineOffset {
            attributes[.baselineOffset] = baselineOffset
        }
        
        attributes[.paragraphStyle] = paragraphStyle
        
        if saleColor != nil {
            attributes[.strikethroughStyle] =  NSUnderlineStyle.single.rawValue
            attributes[.strikethroughColor] = saleColor ?? UIColor.black
        }
        
        if let wordSpacing = wordSpaceing {
            attributes[.kern] = wordSpacing
        }
        
        return NSAttributedString(string: self, attributes: attributes)
    }
    
    func attributed(_ attributes: [NSAttributedString.Key : Any]) -> NSAttributedString {
        return NSAttributedString(string: self, attributes: attributes)
    }
    
    /**
     * 将字符串每隔数位用分隔符隔开
     * @param gap 相隔位数,默认为3
     * @param seperator: 分隔符
     * return 用指定分隔符每隔指定位数隔开的字符串
     */
    
    func showInComma(gap: Int=3, seperator: Character=",") -> String {
        var temp = self
        let count = temp.count
        let sepNum = count / gap
        guard sepNum >= 1 else {
            return temp
        }
        
        for i in 1...sepNum {
            let index = count - gap * i
            guard index != 0 else {
                break
            }
            temp.insert(seperator, at: temp.index(temp.startIndex, offsetBy: index))
        }
        
        return temp
    }
    
    /**
     *    Json字符串转字典
     */
    func getDictionaryFromJSONString() -> Dictionary<String, Any>{
        
        let jsonData: Data = self.data(using: .utf8)!
        let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if dict != nil, let dictionary = dict as? Dictionary<String, Any> {
            return dictionary
            
        }
        return Dictionary()
    }
    
    // MARK: - 计算文本
    /// 根据最大宽度计算得到的最大size -> 高
    func size(for font: UIFont, maxWidth width: CGFloat) -> CGSize {
        let maxSize = CGSize(width: ceil(width), height: CGFloat(MAXFLOAT))
        
        let boundingBox = self.boundingRect(with: maxSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return boundingBox.size
    }
    
    /// 根据给的最大高度 算宽
    func size(for font: UIFont, maxHeight height: CGFloat) -> CGSize {
        let maxSize = CGSize(width: CGFloat(MAXFLOAT), height: ceil(height))
        let boundingBox = self.boundingRect(with: maxSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return boundingBox.size
    }
    
    // 截取url字符串中的参数，转化成对应的字典
    func getUrlParameters() -> [String: String]? {
        var params: [String: String] = [:]
        let array = self.components(separatedBy: "?")
        if array.count == 2 {
            let paramsStr = array[1]
            if paramsStr.count > 0 {
                let paramsArray = paramsStr.components(separatedBy: "&")
                for param in paramsArray {
                    let arr = param.components(separatedBy: "=")
                    if arr.count == 2 {
                        params[arr[0]] = arr[1]
                    }
                }
            }
        }
        return params
    }

    // encodeURIComponent编码
    func encodeURIComponent() -> String {
        let mutSet = NSMutableCharacterSet()
        mutSet.formUnion(with: NSMutableCharacterSet.alphanumeric() as CharacterSet)
        mutSet.formUnion(with: NSMutableCharacterSet.init(charactersIn: "_") as CharacterSet)
        let encodedUrl = self.addingPercentEncoding(withAllowedCharacters: mutSet as CharacterSet)
        return encodedUrl ?? ""
    }
    
    //根据给定的文字及文字大小计算宽度
    static func getTotalGivenStrWidth(givenStr: String, givenFont: UIFont) -> CGFloat {
        if givenStr.isEmpty {
            return 0.0
        }
        
        let givenLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
        givenLabel.font = givenFont
        givenLabel.text = givenStr
        givenLabel.sizeToFit()
        
        return givenLabel.frame.size.width
    }
    
    //根据给定文字及宽度，计算所占高度
    static func getTotalGivenStrHeight(givenStr: String, givenFont: UIFont,lines: Int, givenWidth: CGFloat) -> CGFloat {
        if givenStr.isEmpty {
            return 0.0
        }
        
        let givenLabel = UILabel(frame: CGRect(x: 0, y: 0, width: givenWidth, height: 1))
        givenLabel.font = givenFont
        givenLabel.numberOfLines = lines
        givenLabel.text = givenStr
        givenLabel.sizeToFit()
        
        return givenLabel.frame.size.height
    }
    
    // 价格字符串默认保留2位小数
    func moneyFormatter(digit: Int = 2) -> String {
        let num = digit
        return String(format: "%.\(num)f", Float(self) ?? 0.0)
    }
    
    func urlScheme(scheme:String) -> URL? {
        if let url = URL.init(string: self) {
            var components = URLComponents.init(url: url, resolvingAgainstBaseURL: false)
            components?.scheme = scheme
            return components?.url
        }
        return nil
    }
    
    static func format(decimal:Float, _ maximumDigits:Int = 1, _ minimumDigits:Int = 1) ->String? {
        let number = NSNumber(value: decimal)
        let numberFormatter = NumberFormatter()
        numberFormatter.maximumFractionDigits = maximumDigits //设置小数点后最多2位
        numberFormatter.minimumFractionDigits = minimumDigits //设置小数点后最少2位（不足补0）
        return numberFormatter.string(from: number)
    }
}

internal class TextLayout {
    
    let attributedString: NSAttributedString
    
    let size: CGSize
    
    private let textStorage: NSTextStorage
    
    private let textContainer: NSTextContainer
    
    private let layoutManager: NSLayoutManager
    
    init(attributedString: NSAttributedString, size: CGSize) {
        self.attributedString = attributedString
        self.size = size
        textStorage = NSTextStorage(attributedString: self.attributedString)
        textContainer = NSTextContainer(size: self.size)
        layoutManager = NSLayoutManager()
        
        textContainer.lineFragmentPadding = 0.0
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)
    }
    
    convenience init(string: String, attributes: [NSAttributedString.Key: Any]?, size: CGSize) {
        self.init(attributedString: NSAttributedString(string: string, attributes: attributes), size: size)
    }
    
    /// 获取文本在指定大小容器范围内的实际大小，在MVVM模式的UI布局中，建议也由ViewModel来指定容器大小
    func getBoundingSize() -> CGSize {
        layoutManager.glyphRange(for: textContainer)
        let size = layoutManager.usedRect(for: textContainer).size
        return size
    }
    
    /// 获取文本在指定大小容器范围内的实际行数
    func getNumberOfLines() -> Int {
        var numberOfLines: Int = 0, index: Int = 0
        let numberOfGlyphs = layoutManager.numberOfGlyphs
        var lineRange: NSRange = NSMakeRange(0, 0)
        
        while index < numberOfGlyphs {
            layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
            index = NSMaxRange(lineRange)
            numberOfLines += 1
        }
        return numberOfLines
    }
}

internal extension Date {
    
    /// 获取当前 秒级 时间戳 - 10位
    var timeStamp : String {
        let timeInterval: TimeInterval = self.timeIntervalSince1970
        let timeStamp = Int(timeInterval)
        return "\(timeStamp)"
    }
    
    /// 获取当前 毫秒级 时间戳 - 13位
    var milliStamp : String {
        let timeInterval: TimeInterval = self.timeIntervalSince1970
        let millisecond = CLongLong(round(timeInterval*1000))
        return "\(millisecond)"
    }
}

internal extension UIColor {
    
    /// 颜色生成图片
    static func creatImageWithColor(color:UIColor) -> UIImage{
        let rect = CGRect(x:0,y:0,width:1,height:1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(color.cgColor)
        context!.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }
}

internal extension UIFont {
    // MARK: - 快速创建系统字体对象
    /// 常规体
    static func regular(_ size: CGFloat) -> UIFont {
        return .systemFont(ofSize: size, weight: .regular)
    }
    
    /// 中粗体
    static func medium(_ size: CGFloat) -> UIFont {
        return .systemFont(ofSize: size, weight: .medium)
    }
    
    /// 半粗体
    static func semibold(_ size: CGFloat) -> UIFont {
        return .systemFont(ofSize: size, weight: .semibold)
    }
    
    /// 粗体
    static func bold(_ size: CGFloat) -> UIFont {
        return .systemFont(ofSize: size, weight: .bold)
    }
    
    /// 细体
    static func light(_ size: CGFloat) -> UIFont {
        return .systemFont(ofSize: size, weight: .light)
    }
    
    static func din_alternate_bold(_ size: CGFloat) -> UIFont {
        return UIFont.init(name: "DINAlternate-Bold", size: size.scaled) ?? .semibold(size.scaled)
    }
    
    static func helvetica(_ size: CGFloat) -> UIFont {
        return UIFont.init(name: "Helvetica", size: size.scaled) ?? .semibold(size.scaled)
        
//        return .systemFont(ofSize: size, weight: .heavy)
    }
    
    static func fzzhjw(_ size: CGFloat) -> UIFont {
        return UIFont.init(name: "FZZhengHeiS-DB-GB", size: size.scaled) ?? .semibold(size.scaled)
    }
}


internal extension Double {
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded()/divisor
    }
}

internal extension Float {
    func roundTo(places: Int) -> Float {
        let divisor = pow(10.0, Float(places))
        return (self * divisor).rounded()/divisor
    }
}

public extension Dictionary {
    /**
     *    字典转json字符串
     */
    func convertDictionaryToString() -> String {
        var result:String = ""
        do {
            //如果设置options为JSONSerialization.WritingOptions.prettyPrinted，则打印格式更好阅读
            let jsonData = try JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions.init(rawValue: 0))
            
            if let JSONString = String(data: jsonData, encoding: String.Encoding.utf8) {
                result = JSONString
            }
            
        } catch {
            result = ""
        }
        return result
    }
    
    
    /// url编码方法，转换特殊符号
    func getUrlWithParams() -> String {
        //默认URL
        var urlStr = ""
        var flag = true
        let generalDelimitersToEncode = ":#[]@"
        let subDelimitersToEncode = "!$&'()*+,;="
        var allowedCharacterSet = CharacterSet.urlQueryAllowed
        allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
        for (key,value) in self {
            var anyValue: Any = value
            if let value = value as? String{
                anyValue = value.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? ""
            }
            var dicKey = ""
            if let anyKey = key as? String{
                dicKey = anyKey
            }
            if flag{
                flag = false
                urlStr += "?" + dicKey + "=\(anyValue)"
            }else{
                urlStr += "&" + dicKey + "=\(anyValue)"
            }
        }
        return urlStr
    }
}


public extension NSAttributedString {
    
    /// SwifterSwift: Add a NSAttributedString to another NSAttributedString.
    ///
    /// - Parameters:
    ///   - lhs: NSAttributedString to add to.
    ///   - rhs: NSAttributedString to add.
    static func += (lhs: inout NSAttributedString, rhs: NSAttributedString) {
        let string = NSMutableAttributedString(attributedString: lhs)
        string.append(rhs)
        lhs = string
    }
    
    /// SwifterSwift: Add a NSAttributedString to another NSAttributedString and return a new NSAttributedString instance.
    ///
    /// - Parameters:
    ///   - lhs: NSAttributedString to add.
    ///   - rhs: NSAttributedString to add.
    /// - Returns: New instance with added NSAttributedString.
    static func + (lhs: NSAttributedString, rhs: NSAttributedString) -> NSAttributedString {
        let string = NSMutableAttributedString(attributedString: lhs)
        string.append(rhs)
        return NSAttributedString(attributedString: string)
    }
    
    /// SwifterSwift: Add a NSAttributedString to another NSAttributedString.
    ///
    /// - Parameters:
    ///   - lhs: NSAttributedString to add to.
    ///   - rhs: String to add.
    static func += (lhs: inout NSAttributedString, rhs: String) {
        lhs += NSAttributedString(string: rhs)
    }
    
    /// SwifterSwift: Add a NSAttributedString to another NSAttributedString and return a new NSAttributedString instance.
    ///
    /// - Parameters:
    ///   - lhs: NSAttributedString to add.
    ///   - rhs: String to add.
    /// - Returns: New instance with added NSAttributedString.
    static func + (lhs: NSAttributedString, rhs: String) -> NSAttributedString {
        return lhs + NSAttributedString(string: rhs)
    }
    
}


extension String {
    func getWidth(font: UIFont) -> CGFloat {
        
        let constraint = CGSize(width: 2000, height: font.pointSize)
        let nString = NSString(string: self)
        let size = nString.boundingRect(with: constraint, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context: nil)
        
        return ceil(size.width)
    }
    
    func getHeight(font: UIFont, width: CGFloat, fontMultiple: CGFloat = kDefaultMultiple) -> CGFloat {
        
        let constraint = CGSize(width: width, height: 20000.0)
        let lineHeight = font.pointSize * fontMultiple
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.maximumLineHeight = lineHeight
        paragraphStyle.minimumLineHeight = lineHeight
        // 由于这个方法计算字符串的大小的通过取得字符串的size来计算, 如果你计算的字符串中包含\n\r 这样的字符，也只会把它当成字符来计算。但是在显示的时候就是\n是转义字符，那么显示的计算的高度就不一样了,需要进一步处理
        let nString = NSString(string: self)
        let size = nString.boundingRect(with: constraint, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : paragraphStyle], context: nil)
        
        let totalHeight = ceil(size.height)
        
        return totalHeight
    }
    
    /// 手机号脱敏方法
    func desensitization() -> String {
        guard self.count == 11 else {
            return self
        }
        
        let startIndex = self.index(self.startIndex, offsetBy:3)
        let endIndex = self.index(self.startIndex, offsetBy:6)
        let range = startIndex...endIndex
        return self.replacingCharacters(in: range, with: "****")
    }
    
    /// 接口MD5加密
    /// - Parameters:
    ///   - timestamp: 时间戳
    ///   - nonce: 随机串
    /// - Returns: 加密字符串
//    static func getMD5(timestamp: String, nonce: String) -> String {
//        let appKeyStr = "appKey=\(TJLive_UserDefault.getAppKey())"
//        let nonceStr = "nonce=\(nonce)"
//        let timestampStr = "timestamp=\(timestamp)"
//        let appSecretStr = "appSecret=\(TJLive_UserDefault.getAppSecret())"
//
//        let params = appKeyStr + "&" + nonceStr + "&" + timestampStr + "&" + appSecretStr
//
//        print("🌺MD5 = \(params.md5.uppercased())\n params = \(params)")
//        return params.md5.uppercased()
//    }
    
    //判断是否是主播身份
    static func anchorOrNot(givenIDStr: String) -> Bool {
        
        if givenIDStr.isEmpty {
            return false
        }
        
        var anchor: Bool = false
        if givenIDStr.range(of: "Open_Admin") != nil {
            anchor = true
        }
        
        return anchor
    }
    
    // String删除指定字符
    func removing(charactersOf string: String) -> String {
        let characterSet = CharacterSet(charactersIn: string)
        let components = self.components(separatedBy: characterSet)
        return components.joined(separator: "")
    }
}


extension Bool {
    /// 取反
    /// - Returns: 取反结果
    func reverse() -> Bool {
        !self
    }
}


extension Notification.Name {
    /// 取消第一响应者消息
    static let ResignFirstResponderNotification = Notification.Name(rawValue: "kShopCar_APP_ResignFirstResponder")
    /// 账号被踢重新登录
    static let KickedOutRELogin = Notification.Name(rawValue: "KickedOutRELogin")
}
